package com.arithmetic;

/**
 * This class consists of static methods that allows arithmetical operations on
 * numbers.
 * <p>
 * These methods are:
 * <ul>
 * <li>sum
 * <li>subtract
 * <li>multiply
 * <li>divide
 * <li>power
 * <li>remainder
 * <li>modulus
 * <li>log
 * </ul>
 * <p>
 * The methods of this class may throw a <tt>ArithmeticException</tt> if the
 * operations includes some invalid operation like dividing by zero.
 */
public class Arithmetic {
	
	// Suppresses default constructor, ensuring non-instantiability.
	private Arithmetic() {
	}
	/**
	 * Calculates the sum of any number of operands
	 * 
	 * @return the result of sum of elements and if no elements is given then returns 0
	 * @param numbers an array that can have multiple elements 
	 */
	public static double sum(double... numbers) {
		if (numbers == null) {
			return 0;
		}
		double result = 0;
		for (int i = 0; i < numbers.length; i++) {
			result += numbers[i];
		}
		return result;
	}

	/**
	 * Calculates the subtraction of two operands,
	 * 
	 * @return the result of substraction of operands
	 * @param op1
	 *            first operand
	 * @param op2
	 *            second operand
	 */
	public static int subtract(int op1, int op2) {
		return op1 - op2;
	}

	/**
	 * Multiplies two operands,
	 * 
	 * @return the result of multiplication of operands
	 * @param x
	 *            first operand
	 * @param y
	 *            second operand
	 */
	public static int multiply(int x, int y) {

		if (x > 2147483647 || x < -2147483648 || y > 2147483647
				|| y < -2147483648 ) {

			throw new ArithmeticException();

		} else if ((long) x * (long) y > 2147483647
				|| (long) x * (long) y < -2147483648) {

			throw new ArithmeticException();

		} else {

			return x * y;
		}
	}

	/**
	 * Divides two operands,
	 * 
	 * @return the result of division of operands
	 * @param dividend
	 *            is the first operand
	 * @param divisor
	 *            is the second operand
	 */
	public static  double divide(double dividend, double divisor) {
		try {
			if (divisor == 0) {
				throw new IllegalArgumentException("Argument 'divisor' is 0");
			}
			return dividend / divisor;
		} catch (ArithmeticException e) {
			return 0;
		}
	}
	
	/**
	 * Multiplies base with itself exp times,
	 * 
	 * @return the result of power operation
	 * @param base
	 *            is the base operand
	 * @param exp
	 *            is the power operand
	 */
	public static double power(double base,double exp) {
		if(base == 0 && (exp<0)){
			throw new IllegalArgumentException("Argument 'result' is undefined");
		}
      double result=1;
		for(int i=1;i<=exp;i++){
			result*=base;
		}
		return result;
	}
	/**
	 * calculates remainder 
	 * 
	 * @return the remainder of division operation
	 * @param dividend
	 *            is the first operand
	 * @param divisor
	 *            is the second operand
	 */

	public static int remainder (int dividend, int divisor){
		int x;
		try {
			if (divisor == 0) {
				throw new IllegalArgumentException("Argument 'divisor' is 0");
			}
			 x= dividend / divisor;
			 return dividend - (x * divisor);
		} catch (ArithmeticException e) {
			return 0;
		}
		
	}
	


	/**
	 * Module operation
	 * 
	 * @return first operand module second operand
	 * @param x
	 *            first operand
	 * @param y
	 *            second operand
	 */
	public static int modulus(int x, int y) {
		return x % y;
	}
	
	
	
	
	/**
	 * Logarithm operation
	 * 
	 * @return natural log of x
	 * @param x
	 *            number that will be taken it's logarithm
	 
	 */
	public static double log(double x) {
		return Math.log(x);
	}
	
}
